package com.micro.ai.files.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.micro.ai.commons.exception.BusinessException;
import com.micro.ai.files.entity.StorageQuota;
import com.micro.ai.files.mapper.StorageQuotaMapper;
import com.micro.ai.files.service.StorageQuotaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * 存储配额服务实现
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Service
public class StorageQuotaServiceImpl extends ServiceImpl<StorageQuotaMapper, StorageQuota> implements StorageQuotaService {

    private static final long DEFAULT_TOTAL_QUOTA = 5368709120L; // 5GB
    private static final long DEFAULT_MAX_FILE_SIZE = 1073741824L; // 1GB
    private static final int DEFAULT_WARNING_THRESHOLD = 90;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StorageQuota getOrCreate(String tenantId) {
        if (!StringUtils.hasText(tenantId)) {
            throw new BusinessException("F0000", "租户ID不能为空");
        }
        
        LambdaQueryWrapper<StorageQuota> query = new LambdaQueryWrapper<>();
        query.eq(StorageQuota::getTenantId, tenantId);
        
        StorageQuota quota = this.getOne(query);
        
        if (quota == null) {
            quota = new StorageQuota();
            quota.setTenantId(tenantId);
            quota.setTotalQuota(DEFAULT_TOTAL_QUOTA);
            quota.setUsedStorage(0L);
            quota.setUsedTrashStorage(0L);
            quota.setFileCount(0);
            quota.setMaxFileSize(DEFAULT_MAX_FILE_SIZE);
            quota.setWarningThreshold(DEFAULT_WARNING_THRESHOLD);
            quota.setUpdatedAt(LocalDateTime.now());
            
            this.save(quota);
            log.info("创建存储配额成功: tenantId={}", tenantId);
        }
        
        return quota;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StorageQuota update(String id, StorageQuota quota) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("F0000", "配额ID不能为空");
        }
        if (quota == null) {
            throw new BusinessException("F0000", "配额信息不能为空");
        }
        
        StorageQuota existing = this.getById(id);
        if (existing == null) {
            throw new BusinessException("F0002", "存储配额不存在: " + id);
        }
        
        quota.setId(id);
        quota.setUpdatedAt(LocalDateTime.now());
        
        boolean success = this.updateById(quota);
        if (!success) {
            throw new BusinessException("F0003", "更新存储配额失败");
        }
        
        log.info("更新存储配额成功: quotaId={}, tenantId={}", id, existing.getTenantId());
        return quota;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void increaseUsedStorage(String tenantId, Long size) {
        if (size == null || size <= 0) {
            return;
        }
        
        StorageQuota quota = getOrCreate(tenantId);
        quota.setUsedStorage((quota.getUsedStorage() == null ? 0L : quota.getUsedStorage()) + size);
        quota.setUpdatedAt(LocalDateTime.now());
        this.updateById(quota);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void decreaseUsedStorage(String tenantId, Long size) {
        if (size == null || size <= 0) {
            return;
        }
        
        StorageQuota quota = getOrCreate(tenantId);
        long usedStorage = quota.getUsedStorage() == null ? 0L : quota.getUsedStorage();
        long newUsedStorage = Math.max(0, usedStorage - size);
        quota.setUsedStorage(newUsedStorage);
        quota.setUpdatedAt(LocalDateTime.now());
        this.updateById(quota);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void increaseFileCount(String tenantId) {
        StorageQuota quota = getOrCreate(tenantId);
        quota.setFileCount((quota.getFileCount() == null ? 0 : quota.getFileCount()) + 1);
        quota.setUpdatedAt(LocalDateTime.now());
        this.updateById(quota);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void decreaseFileCount(String tenantId) {
        StorageQuota quota = getOrCreate(tenantId);
        int fileCount = quota.getFileCount() == null ? 0 : quota.getFileCount();
        quota.setFileCount(Math.max(0, fileCount - 1));
        quota.setUpdatedAt(LocalDateTime.now());
        this.updateById(quota);
    }

    @Override
    public boolean checkQuota(String tenantId, Long fileSize) {
        if (fileSize == null || fileSize <= 0) {
            return true;
        }
        
        StorageQuota quota = getOrCreate(tenantId);
        
        // 检查单文件大小限制
        if (quota.getMaxFileSize() != null && fileSize > quota.getMaxFileSize()) {
            return false;
        }
        
        // 检查总配额
        long usedStorage = quota.getUsedStorage() == null ? 0L : quota.getUsedStorage();
        long totalQuota = quota.getTotalQuota() == null ? DEFAULT_TOTAL_QUOTA : quota.getTotalQuota();
        
        return (usedStorage + fileSize) <= totalQuota;
    }

    @Override
    public double getUsageRate(String tenantId) {
        StorageQuota quota = getOrCreate(tenantId);
        
        long usedStorage = quota.getUsedStorage() == null ? 0L : quota.getUsedStorage();
        long totalQuota = quota.getTotalQuota() == null ? DEFAULT_TOTAL_QUOTA : quota.getTotalQuota();
        
        if (totalQuota == 0) {
            return 0.0;
        }
        
        return (double) usedStorage / totalQuota * 100;
    }
}

